import sys
from simpledcpp.core.base import DCPPPart, DCPPEvent


class Segment(DCPPPart):
	""" Class realize array of segments for file with filesize """
	def __init__(self,parent,filesize, initialize = True):
		""" Initialization if initialize == True """
		self.filesize = filesize
		if self.filesize == None:
			self.filesize = -1
		DCPPPart.__init__(self, parent)
		self.segments = {}
		if initialize and (filesize != 0 and filesize != None):
			# Get segment size from settings
			SEGMENT_SIZE = int(self.settings.get("segment_size", 1000000))
			# Create dictionary with [segment_num] == segment (Busy, From, To)
			for i in range(0,int(filesize/SEGMENT_SIZE)):
				self.segments[i] = (0,i*SEGMENT_SIZE,i*SEGMENT_SIZE + SEGMENT_SIZE) # STATUS, FROM, TO
			if filesize % SEGMENT_SIZE > 0:
				self.segments[int(filesize/SEGMENT_SIZE)] = (0, int(filesize/SEGMENT_SIZE)*SEGMENT_SIZE, int(filesize/SEGMENT_SIZE)*SEGMENT_SIZE + filesize % SEGMENT_SIZE)
		#If not initialize create one segment.
		elif (filesize == 0 or filesize == None) and initialize:
			self.segments[0] = (0,0,-1)
			self.filesize = -1

	def _free(self, segment):
		""" Free segment. """
		if not self.segments.has_key(segment):
			return False
		if self.segments[segment][0] == 0:
			return True
		else:
			return False

	def update(self, segment, newto):
		""" Update segment. Set new field TO. """
		self.segments[segment] = (self.segments[segment][0], self.segments[segment][1], int(newto))

	def require(self):
		""" Acquire segment. """
		for i in self.segments:
			if self.segments[i][0] == 0 and self.segments[i][1] != self.segments[i][2]:
				self.segments[i] = (1,self.segments[i][1],self.segments[i][2])
				return (i, self.segments[i][1], self.segments[i][2])
		return None

	def free(self, segment, dbytes):
		""" Free segment and set new field FROM to dbytes.
		Generate EVENT == QUEUE_UPDATED.  """
		self.segments[segment] = (0,dbytes + self.segments[segment][1],self.segments[segment][2])
		self.Event(DCPPEvent("QUEUE_UPDATED",(self.parent,)))

	def hasFree(self):
		""" Function return true if Segment have free segments. """
		for i in self.segments:
			if int(self.segments[i][0]) == 0 and int(self.segments[i][1]) != int(self.segments[i][2]):
				return True
		return False

	def percent(self):
		""" Return count loaded segments in percents. """
		"""
		if self.filesize <= 0:
			return 0
		loaded = 0
		for i in self.segments:
			sum = self.segments[i][2] - self.segments[i][1]
			if sum < 0:
				print self.segments[i][2], self.segments[i][1], i, sum
			loaded = loaded + sum
		ret = int((float(loaded)/float(self.filesize))*100.0)
		return ret

		# old code.
		"""
		elapsed = 0
		all = 0
		for i in self.segments:
			elapsed = self.segments[i][2] - self.segments[i][1] + elapsed
			all = self.segments[i][2]
		loaded = all - elapsed
		if float(all) != 0:
			ret = float(float(float(loaded)/float(all)) * 100.0)
			if ret < 0 :
				ret = 0
			return ret
		else:
			return 100.0

class Source:
	""" Source. """
	locked = 0
	nickname = None
	hubname = None
	def __init__(self, nickname, hubname = None):
		""" Initialize source. """
		self.locked = 0
		self.nickname = nickname
		self.hubname = hubname

	def acquire(self):
		""" Acquire source. """
		self.locked = 1

	def release(self):
		""" Release source. """
		self.locked = 0

	def is_free(self):
		""" Check source is free. """
		return not self.locked


class SourceManager(DCPPPart):
	""" Manager of sources. """
	sources = []
	def __init__(self, parent):
		DCPPPart.__init__(self, parent)
		self.sources = []

	def add(self, nickname, hubname = None):
		""" Add new source. Generate event. """
		for i in self.sources:
			if i.nickname == nickname and i.hubname == hubname:
				return False
		src = Source(nickname, hubname)
		self.sources.append(src)
		self.Event(DCPPEvent("QUEUE_UPDATED",(self.parent,)))
		return src

	def remove(self, nickname, hubname = None):
		""" Remove source. """
		removed = None
		for i in self.sources:
			if i.nickname == nickname and i.hubname == hubname:
				removed = i
		if removed != None:
			try:
				self.sources.remove(removed)
			except:
				pass
			return True
		else:
			return False

	def acquire(self, nick, hubname = None):
		""" Acquire source. """
		for i in self.sources:
			if i.nickname == nick and (i.hubname == hubname or hubname == None) and i.is_free():
				i.acquire()
				return True
		return False

	def release(self, nick, hubname = None):
		""" Free source. """
		for i in self.sources:
			if i.nickname == nick and (i.hubname == hubname or hubname == None) and (not i.is_free()):
				i.release()
				return True
		return False

	def generator(self):
		""" Generator of sources. """
		for i in self.sources:
			yield i

	def generatorFree(self):
		""" Generator of free sources. """
		for i in self.sources:
			if i.is_free():
				yield i

class Task(DCPPPart):
	""" Task class. """
	def __init__(self, parent, TTH, filesize, localfilename, priority = 3, initialize = True, METADATA = None):
		""" Initialize task. """
		try:
			DCPPPart.__init__(self, parent)
			self.METADATA = METADATA
			self.sources = SourceManager(self)
			if initialize:
				priority = int(priority)
				if priority < 0: priority = 0
				if priority > 10: priority = 10
				self.priority = int(priority)
				self.filesize = filesize
				self.localfilename = localfilename
				self.TTH = TTH
				self.segment = Segment(self, filesize)
		except:
			print _("Error initialize task.")

	def AddSource(self, nick, hubname = None):
		""" Add new source for task. """
		src = self.sources.add(nick, hubname)
		self.Event(DCPPEvent("ON_ADD_SOURCE",(self, src)))

	def RequestSource(self, nick, hubname = None):
		""" Request source for task. """
		return self.sources.acquire(nick, hubname)

	def FreeSource(self, nick, hubname = None):
		""" Free source for task. """
		return self.sources.release(nick, hubname)
